package com.strongbj.iot.devices.newlight.response.handle;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.strongbj.core.message.IMessageHandle;
import com.strongbj.core.util.ByteUtil;
import com.strongbj.core.util.ContextUtils;
import com.strongbj.iot.devices.newlight.entity.AutomaticInventoryTagReturnData;
import com.strongbj.iot.devices.newlight.entity.T;
import com.strongbj.iot.devices.newlight.entity.Tag;
import com.strongbj.iot.devices.newlight.entity.UnBindTagData;
import com.strongbj.iot.devices.newlight.message.NewLightMQMessage;
import com.strongbj.iot.devices.newlight.message.NewLightOSMessageFactory;
import com.strongbj.iot.devices.newlight.message.NewLightReaderMessage;
import com.strongbj.iot.devices.newlight.response.common.HandleTimeStamp;
import com.strongbj.iot.devices.newlight.service.TagService;
import com.strongbj.iot.mq.producer.TopicSender;

import cn.hutool.core.date.DateUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

/**
 * 0x35，标签失联 
 * @author lei_w
 *
 */
public class TagLoseResponseHandle implements IMessageHandle<NewLightReaderMessage, Object> {

	private static Logger logger = LogManager.getLogger(LowBatteryResponseHandle.class.getName());
	
	private TagService tagService = (TagService) ContextUtils.getBean("tagService");
	
	private NewLightOSMessageFactory newLightOSMessageFactory = (NewLightOSMessageFactory) ContextUtils.getBean("newLightOSMessageFactory");
	
	private TopicSender topicSender = (TopicSender) ContextUtils.getBean("topicSender");

	private ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
	
	@Override
	public boolean isHandle(NewLightReaderMessage t) {
		if (Integer.valueOf("35", 16).byteValue() == t.getType()) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Object handle(ChannelHandlerContext ctx, NewLightReaderMessage t) {
		String hostNumber = ByteUtil.bytesToAddress(t.getAddress()); // reader 地址码
		String timeStamp = ByteUtil.byteArrToHexString(t.getTime()); // 时间戳

		short loseNum = ByteUtil.byteArrToShort(t.getBody()); // 失联个数
		byte[][] bTags = new byte[loseNum][5];
		String loseTagIP = "";
		for(int i = 0; i < loseNum; i++) {
			loseTagIP += ByteUtil.bytesToIp(ByteUtil.subBytes(t.getBody(), i * 4 + 2, 4)) + "$";
			System.arraycopy(t.getBody(), i * 4 + 2, bTags[i], 0, 4);
		}
		if(loseTagIP.endsWith("$")) {
			loseTagIP = loseTagIP.substring(0, loseTagIP.lastIndexOf("$"));
		}

		String log = "\r\n===================================================" +
				"\r\n收到标签失联报文：" + 
				"\r\nREADER地址码：" + hostNumber + 
				"\r\n失联个数：" + loseNum + 
				"\r\n失联标签地址：" + loseTagIP + 
				"\r\n时间戳：" + HandleTimeStamp.handle(timeStamp) + 
				"\r\n===================================================";
		logger.info(log);
		String[] ips = loseTagIP.split("\\$");
		List<Tag> tags = new ArrayList<Tag>();
		List<String> cards = new ArrayList<String>();
		for(String ip : ips) {
			Tag tag = new Tag();
			tag.setIp(ip);
			tag.setState(2);
			tags.add(tag);
			cards.add(ip);
		}
		tagService.updateBatchById(tags);
		
		// TODO 临时测试用，故加上时间延时。
//		try {
//			Thread.sleep(20000);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		// 下发盘点指令
		for(byte[] tag : bTags) {
			this.sendTagInventoryCommand(tag,t.getAddress(), ctx);
			String tagCode = ByteUtil.bytesToIp(ByteUtil.subBytes(tag, 0, 4));
			threadPool.schedule(new PushTagLosetMessageRunnble(ByteUtil.bytesToAddress(t.getAddress()),tagCode), 60, TimeUnit.SECONDS);
		}
		
//		byte[] sendData = new byte[ips.length * 4 + 2];
//		ByteUtil.intToByteArray(loseNum);
//		for(int i=0 ; i<ips.length ; i++) {
//			byte[] data = ByteUtil.ipToBytesByInet(ips[i]);
//    		System.arraycopy(data, 0, sendData, i * 4 + 2, 4);
//		}
//		byte[] req = newLightOSMessageFactory.createNewLightOSMessage(
//				t.getAddress(), (byte) 0x02, sendData, T.getTimeStamp());
//		ByteBuf bs  = Unpooled.copiedBuffer(req);
//		NetMapping.getInstance().getChannels().writeAndFlush(bs);
		AutomaticInventoryTagReturnData aitr = new AutomaticInventoryTagReturnData();
		aitr.setState(2);
		aitr.setReaderCode(hostNumber);
		aitr.setTags(cards);
		NewLightMQMessage mes = new NewLightMQMessage();
		mes.setActioncode("automaticInventoryTag");
		mes.setGUID(String.valueOf(DateUtil.date().getTime()));
		mes.setPostdata(aitr);
		logger.info("=========automaticInventoryTagReturn=======" + JSON.toJSONString(mes));
		topicSender.send("wh.reader."+hostNumber+".message", JSON.toJSONString(mes));
		return mes;
	}

	@Override
	public void destory() {
		if(this.threadPool!=null) {
			this.threadPool.shutdown();
		}
	}
	
	private void sendTagInventoryCommand(byte[] datas,byte[] deviceCode, ChannelHandlerContext ctx) {
		datas[4]=0;
		byte[] req = newLightOSMessageFactory.createNewLightOSMessage(
				deviceCode, (byte) 0x07, datas, T.getTimeStamp());
		ByteBuf bs  = Unpooled.copiedBuffer(req);
		ChannelFuture cf = ctx.channel().writeAndFlush(bs);
		cf.addListener(new ChannelFutureListener() {

			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				if (future.isSuccess()) {
					logger.info("标签失联后发送标签盘点命令成功 设备编号:{} 标签编号:{} 命令:{}",
							ByteUtil.bytesToAddress(deviceCode), ByteUtil.bytesToIp(ByteUtil.subBytes(datas, 0, 4)),
							ByteUtil.byteArrToHexString(datas, true));
				} else {
					logger.info("标签失联后发送标签盘点命令失败 设备编号:{} 标签编号:{} 命令:{}",
							ByteUtil.bytesToAddress(deviceCode), ByteUtil.bytesToIp(ByteUtil.subBytes(datas, 0, 4)),
							ByteUtil.byteArrToHexString(datas, true));
				}
			}

		});
	}
	
	/**
	 * 上传标签失联信息
	 * @author yuzhantao
	 *
	 */
	class PushTagLosetMessageRunnble implements Runnable{
		private String tag;
		private String deviceCode;
		
		public PushTagLosetMessageRunnble(String deviceCode, String tag) {
			this.tag=tag;
			this.deviceCode=deviceCode;
		}
		@Override
		public void run() {
			QueryWrapper<Tag> wrapper = new QueryWrapper<Tag>();
			wrapper.eq("ip_", this.tag);
			wrapper.eq("state_", 2);
			Tag tag = tagService.getOne(wrapper);
			// 如果没有查到状态等于2（失联）的，则认为已经找到。
			if(tag==null) return;
			// TODO 未完成发送到MQ功能
			this.sendUnbindTagMessageToMQ(this.deviceCode, this.tag); // 当向失联标签发送重绑命令无效后，发送解绑命令。
			this.sendLoseMessageToMQ(this.deviceCode, this.tag);
			
			logger.info("发送失联信息到MQ 标签编号:{}",this.tag);
		}
		
		/**
		 * 发送解绑标签命令（让设备解绑此标签）
		 */
		private void sendUnbindTagMessageToMQ(String deviceCode,String tag) {
			NewLightMQMessage mqMsg = new NewLightMQMessage();
			mqMsg.setActioncode("unbindTag");
			mqMsg.setGUID(UUID.randomUUID().toString());
			
			UnBindTagData unbind = new UnBindTagData();
			unbind.setReaderCode(deviceCode);
			List<String> tags = new ArrayList<>();
			tags.add(tag);
			unbind.setTags(tags);
			mqMsg.setPostdata(unbind);
			topicSender.send("wh.reader.command.request", JSON.toJSONString(mqMsg));
		}
		
		/**
		 * 发送标签失联信息到MQ
		 */
		private void sendLoseMessageToMQ(String deviceCode,String tag) {
			NewLightMQMessage mes = new NewLightMQMessage();
			mes.setActioncode("automaticInventoryTag");
			mes.setGUID(String.valueOf(DateUtil.date().getTime()));
			
			Map<String,Object> result = new HashMap<>();
			result.put("tag", tag);
			result.put("readerCode", deviceCode);
			mes.setPostdata(result);
			logger.info("=========automaticInventoryTagReturn=======" + JSON.toJSONString(mes));
			topicSender.send("wh.reader."+deviceCode+".message", JSON.toJSONString(mes));
		}
	}
}
